import generateRobotReply from '../utils/robot'
import friendService from '../services/friend.service';
import userService from '../services/user.service';
import groupService from '../services/group.service';
import messageService from '../services/message.service';
import { FileType, MessageType } from '@prisma/client';
import { wsClients } from './index';
import { ROBOT_ID } from '../constants/normal.constants';

type BaseMessage = {
    senderId: string;
    receiverId?: string;
    groupId?: string;
    content: string;
    type: MessageType;
    fileSize?: number
    fileName?: string
    fileType?: FileType
    fileUuid?: string
}
type UserMessage = BaseMessage & {
    receiverId: string;
}
type GroupMessage = BaseMessage & {
    groupId: string;
}

type DataType = 'notice' | 'message' | 'request' | 'contact'

export const sendUserMessage = async (dataType: DataType, data: any, receiverId: string) => {
    const ws = wsClients.get(receiverId)
    const message = {
        dataType,
        data
    }
    if (ws) {
        ws.send(JSON.stringify(message))
    } else {
        console.error('send message failed, ws receiver not exist or closed')
    }
}

export const sendGroupMessage = async (dataType: DataType, data: any, groupId: string) => {
    const groupMembers = await groupService.getGroupMembers(groupId);
    for (const member of groupMembers) {
        sendUserMessage(dataType, data, member.userId)
    }
}

export const sendFriendMessage = async (dataType: DataType, data: any, userId: string) => {
    const friends = await friendService.getFriends(userId);
    for (const friend of friends) {
        sendUserMessage(dataType, data, friend.friendId)
    }
}

export const sendNotice = async (data: { type: 'success' | 'warning' | 'error', message: string, receiverId: string, groupId?: string }) => {
    if (data.groupId) {
        sendGroupMessage('notice', data, data.groupId)
    } else {
        sendUserMessage('notice', data, data.receiverId)
    }
}

export default async function processMessage(msg: BaseMessage) {
    //user message
    const ws = wsClients.get(msg.senderId)
    if (!ws && msg.senderId !== ROBOT_ID) {
        return { message: 'you are offline', success: false }
    }
    if (msg.receiverId) {
        const message = msg as UserMessage
        const friendInfo = await userService.findUserByUserId(message.receiverId)
        if (!friendInfo || friendInfo.status == 'BANNED') {
            return { message: 'user not found', success: false }
        }

        const createdMessage = await messageService.createUserMessage(message);
        sendUserMessage('message', createdMessage, createdMessage.senderId)
        if (message.receiverId === ROBOT_ID) {
            const robotReply = generateRobotReply(createdMessage.content)
            const robotData = {
                senderId: ROBOT_ID,
                receiverId: message.senderId,
                content: robotReply,
                type: 'TEXT' as MessageType,
            }
            setTimeout(async () => {
                const robotMessage = await messageService.createUserMessage(robotData)
                sendUserMessage('message', robotMessage, robotMessage.receiverId);
            }, 3000)
        } else if (message.senderId !== message.receiverId) {
            sendUserMessage('message', createdMessage, createdMessage.receiverId);
        }
    }
    //group message
    else {
        const message = msg as GroupMessage
        const conatctInfo = await groupService.getGroup(message.groupId)
        if (!conatctInfo || conatctInfo.status !== 'NORMAL') {
            return { message: 'group has disbanded', success: false }
        }
        const createdMessage = await messageService.createGroupMessage(message)
        sendGroupMessage('message', createdMessage, message.groupId)
    }
    return { message: 'sended', success: true }
}
